Node.js Child Process Module

Node.js இல் குழந்தை செயல்முறைகளை உருவாக்கவும் நிர்வகிக்கவும் கற்றுக்கொள்ளுங்கள்

Child Process தொகுதி என்றால் என்ன?

Child Process தொகுதி என்பது உள்ளமைக்கப்பட்ட Node.js தொகுதியாகும், இது குழந்தை செயல்முறைகளை உருவாக்கவும் நிர்வகிக்கவும் உங்களை அனுமதிக்கிறது.

இது வெளிப்புற கட்டளைகளை இயக்கவும் துணைச் செயல்முறை நிகழ்வுகளுடன் தொடர்பு கொள்ளவும் பல வழிகளை வழங்குகிறது.

இந்த திறன் பின்வரும் பணிகளுக்கு அவசியம்:

கணினி கட்டளைகளை இயக்குதல்

உங்கள் Node.js பயன்பாட்டிலிருந்து கணினி கட்டளைகளை இயக்கவும்

CPU-தீவிர பணிகளை இயக்குதல்

தனி செயல்முறைகளில் CPU-தீவிர பணிகளை இயக்கவும்

இணை செயல்முறைகள்

பல CPU கோர்களைப் பயன்படுத்த பல செயல்முறைகளை இணையாக இயக்கவும்

வெளிப்புற நிரல்களுடன் இடைமுகம்

வெளிப்புற நிரல்கள் மற்றும் ஸ்கிரிப்ட்களுடன் இடைமுகப்படுத்தவும்

Child Process தொகுதியை இறக்குமதி செய்தல்

Child Process தொகுதி Node.js இல் இயல்பாகச் சேர்க்கப்பட்டுள்ளது.

உங்கள் ஸ்கிரிப்ட்டில் அதைத் தேவைப்படுவதன் மூலம் பயன்படுத்தலாம்:

const childProcess = require('child_process');

// Or using destructuring to access specific methods
const { exec, spawn, fork } = require('child_process');

குழந்தை செயல்முறைகளை உருவாக்கும் முறைகள்

Child Process தொகுதி குழந்தை செயல்முறைகளை உருவாக்கவும் நிர்வகிக்கவும் நான்கு முதன்மை முறைகளை வழங்குகிறது, ஒவ்வொன்றும் வெவ்வேறு நடத்தைகள் மற்றும் பயன்பாட்டு வழக்குகளைக் கொண்டுள்ளது:

முறை விளக்கம் பயன்பாட்டு வழக்கு
exec() ஒரு ஷெல்லைத் தோற்றுவித்து ஒரு கட்டளையை இயக்குகிறது, வெளியீட்டை பஃப்பர் செய்கிறது ஒரு ஷெல் கட்டளையை இயக்க வேண்டும் மற்றும் முழு வெளியீட்டையும் ஒரே முறையில் பெற வேண்டும் போது
execFile() exec() போன்றது ஆனால் ஷெல்லைத் தோற்றுவிக்காது ஷெல் விளக்கமின்றி கோப்பு-அடிப்படையிலான கட்டளைகளை இயக்குவதற்கு மிகவும் திறமையானது
spawn() ஷெல் உருவாக்காமல் ஒரு புதிய செயல்முறையைத் தோற்றுவிக்கிறது, ஸ்ட்ரீமிங் I/O உடன் நீண்ட-இயங்கும் செயல்முறைகள் அல்லது பெரிய வெளியீட்டைக் கையாளும் போது
fork() Node.js செயல்முறைகளை உருவாக்குவதற்கான spawn() இன் ஒரு சிறப்பு வழக்கு மற்றொரு Node.js தொகுதியை தனி செயல்முறையாக IPC உடன் இயக்க வேண்டும் போது

exec() முறை

exec() முறை ஒரு ஷெல்லை உருவாக்கி அந்த ஷெல்லுக்குள் ஒரு கட்டளையை இயக்குகிறது.

இது முழு வெளியீட்டையும் பஃப்பர் செய்து கட்டளை நிறைவடையும் போது ஒரு கால்பேக் மூலம் வழங்குகிறது.

const { exec } = require('child_process');

// Execute the 'ls -la' command (or 'dir' on Windows)
const command = process.platform === 'win32' ? 'dir' : 'ls -la';

exec(command, (error, stdout, stderr) => {
  if (error) {
    console.error(`Error executing command: ${error.message}`);
    return;
  }

  if (stderr) {
    console.error(`Command stderr: ${stderr}`);
  }

  console.log(`Command output:\n${stdout}`);
});

// With options
exec('echo $HOME', {
  env: { HOME: '/custom/home/directory' }
}, (error, stdout, stderr) => {
  console.log(`Custom home directory: ${stdout.trim()}`);
});

⚠️ எச்சரிக்கை:

exec() க்கு சுத்திகரிக்கப்படாத பயனர் உள்ளீட்டை ஒருபோதும் அனுப்ப வேண்டாம், ஏனெனில் இது முழு ஷெல் தொடரியல் கொண்ட கட்டளைகளை இயக்குகிறது, இது கட்டளை ஊசி தாக்குதல்களுக்கு வழிவகுக்கும்.

Promise உடன் exec()

கால்பேக்கைக் கையாள ஒரு promise wrapper ஐப் பயன்படுத்துதல்:

const { exec } = require('child_process');
const util = require('util');

// Convert exec to a promise-based function
const execPromise = util.promisify(exec);

async function executeCommand(command) {
  try {
    const { stdout, stderr } = await execPromise(command);

    if (stderr) {
      console.error(`Command stderr: ${stderr}`);
    }

    console.log(`Command output:\n${stdout}`);
    return stdout;
  } catch (error) {
    console.error(`Error executing command: ${error.message}`);
    throw error;
  }
}

// Using the promise-based function
executeCommand('node --version')
  .then(version => console.log(`Node.js version: ${version.trim()}`))
  .catch(err => console.error('Failed to get Node.js version'));

execFile() முறை

execFile() முறை exec() போன்றது, ஆனால் அது ஒரு ஷெல்லைத் தோற்றுவிக்காது.

வெளிப்புற பைனரிகளை இயப்பதற்கு இது மிகவும் திறமையானது.

const { execFile } = require('child_process');

// Execute 'node' with arguments
execFile('node', ['--version'], (error, stdout, stderr) => {
  if (error) {
    console.error(`Error executing file: ${error.message}`);
    return;
  }

  console.log(`Node.js version: ${stdout.trim()}`);
});

// On Windows, execute a batch file
if (process.platform === 'win32') {
  execFile('C:\\Windows\\System32\\cmd.exe', ['/c', 'echo Hello from batch!'], (error, stdout, stderr) => {
    if (error) {
      console.error(`Error: ${error.message}`);
      return;
    }

    console.log(`Output: ${stdout.trim()}`);
  });
}

🔒 குறிப்பு:

execFile() பயனர் உள்ளீட்டுடன் கட்டளைகளை இயக்குவதற்கு exec() ஐ விட மிகவும் பாதுகாப்பானது, ஏனெனில் இது ஷெல் மெட்டா எழுத்துகளை செயலாக்காது.

spawn() முறை

spawn() முறை கொடுக்கப்பட்ட கட்டளையுடன் ஒரு புதிய செயல்முறையைத் தொடங்குகிறது.

exec() போலன்றி, இது வெளியீட்டை பஃப்பர் செய்யாது, மாறாக stdout மற்றும் stderr க்கு ஸ்ட்ரீம்-அடிப்படையிலான அணுகலை வழங்குகிறது.

const { spawn } = require('child_process');

// Spawn a process to list files
const ls = process.platform === 'win32'
  ? spawn('cmd', ['/c', 'dir'])
  : spawn('ls', ['-la']);

// Handle process output streams
ls.stdout.on('data', (data) => {
  console.log(`stdout: ${data}`);
});

ls.stderr.on('data', (data) => {
  console.error(`stderr: ${data}`);
});

ls.on('close', (code) => {
  console.log(`Child process exited with code ${code}`);
});

// Spawn with options
const grep = spawn('grep', ['hello', 'input.txt'], {
  cwd: '/tmp', // Working directory
  env: { ...process.env, CUSTOM_ENV: 'value' },
  stdio: 'pipe', // Configure stdio
  detached: false, // Process group behavior
  shell: false // Whether to run in a shell
});

// Handling errors
grep.on('error', (err) => {
  console.error(`Failed to start subprocess: ${err.message}`);
});

spawn() ஐ எப்போது பயன்படுத்துவது

spawn() குறிப்பாக பயனுள்ளதாக இருக்கும்:

நீண்ட-இயங்கும் செயல்முறைகள் (சேவையக செயல்முறைகள் அல்லது கண்காணிப்பாளர்கள் போன்றவை)
பெரிய அளவிலான வெளியீட்டை உருவாக்கும் செயல்முறைகள்
நிறைவுக்காகக் காத்திருக்காமல் தரவு உருவாக்கப்படும்போது அதைச் செயலாக்க வேண்டிய போது

stdin உடன் spawn() பயன்படுத்துதல்

const { spawn } = require('child_process');

// Spawn a process that reads from stdin
const process = spawn('wc', ['-w']); // Word count

// Send data to the process's stdin
process.stdin.write('Hello world from Node.js!');
process.stdin.end(); // Signal the end of input

// Capture output
process.stdout.on('data', (data) => {
  console.log(`Number of words: ${data}`);
});

fork() முறை

fork() முறை என்பது Node.js செயல்முறைகளை உருவாக்குவதற்கான spawn() இன் ஒரு சிறப்பு வழக்காகும். இது பெற்றோர் மற்றும் குழந்தை செயல்முறைகளுக்கு இடையே செய்திகளை அனுப்ப அனுமதிக்கும் ஒரு IPC சேனலை அமைக்கிறது.

// In the main file (parent.js)
const { fork } = require('child_process');

// Fork a child process
const child = fork('child.js');

// Send a message to the child
child.send({ message: 'Hello from parent' });

// Receive messages from the child
child.on('message', (message) => {
  console.log('Message from child:', message);
});

// Handle child process exit
child.on('close', (code) => {
  console.log(`Child process exited with code ${code}`);
});
// In the child file (child.js)
console.log('Child process started', process.pid);

// Listen for messages from the parent
process.on('message', (message) => {
  console.log('Message from parent:', message);

  // Send a message back to the parent
  process.send({ response: 'Hello from child' });

  // After 3 seconds, exit the process
  setTimeout(() => {
    process.exit(0);
  }, 8080);
});

fork() இன் நன்மைகள்

ஒவ்வொரு forked செயல்முறையும் அதன் சொந்த V8 நிகழ்வு மற்றும் நினைவகத்தைப் பெறுகிறது
முக்கிய இவெண்ட் லூப்பிலிருந்து CPU-தீவிர வேலையை தனிமைப்படுத்துகிறது
செயல்முறைகளுக்கு இடையே செய்திகள் மூலம் தொடர்பு கொள்ள அனுமதிக்கிறது
பல CPU கோர்களைப் பயன்படுத்த உதவுகிறது

செயல்முறைக்கு இடையேயான தொடர்பு (IPC)

fork() உடன் உருவாக்கப்பட்ட குழந்தை செயல்முறைகள் send() மற்றும் message event ஐப் பயன்படுத்தி உள்ளமைக்கப்பட்ட IPC சேனல் மூலம் பெற்றோர் செயல்முறையுடன் தொடர்பு கொள்ள முடியும்.

சிக்கலான தரவை அனுப்புதல்

// In parent.js
const { fork } = require('child_process');
const child = fork('worker.js');

// Send different types of data
child.send({
  command: 'compute',
  data: [1, 2, 3, 4, 5],
  options: {
    multiply: 2,
    subtract: 1
  }
});

// Receive the result
child.on('message', (result) => {
  console.log('Computation result:', result);
  child.disconnect(); // Clean up the IPC channel
});
// In worker.js
process.on('message', (msg) => {
   if (msg.command === 'compute') {
    const result = msg.data.map(num => num * msg.options.multiply - msg.options.subtract);

    // Send the result back to the parent
    process.send({ result });
  }
});

💬 குறிப்பு:

செய்திகள் JSON ஐப் பயன்படுத்தி தொடரப்படுகின்றன, எனவே நீங்கள் JSON-இணக்க தரவை மட்டுமே அனுப்ப முடியும் (பொருள்கள், வரிசைகள், சரங்கள், எண்கள், பூலியன்கள் மற்றும் null).

குழந்தை செயல்முறைகளை நிர்வகித்தல்

குழந்தை செயல்முறையைக் கொல்லுதல்

const { spawn } = require('child_process');

// Spawn a long-running process
const child = spawn('node', ['-e', `
  setInterval(() => {
    console.log('Still running...', Date.now());
  }, 1000);
`]);

// Output from the process
child.stdout.on('data', (data) => {
  console.log(`stdout: ${data}`);
});

// Kill the process after 5 seconds
setTimeout(() => {
  console.log('Killing the child process...');

  // Send a SIGTERM signal
  child.kill('SIGTERM');

  // Alternative: child.kill() - uses SIGTERM by default
}, 5000);

// Handle the exit event
child.on('exit', (code, signal) => {
  console.log(`Child process exited with code ${code} and signal ${signal}`);
});

பிரிக்கப்பட்ட செயல்முறைகள்

பெற்றோரிடமிருந்து சுயாதீனமாக தொடர்ந்து இயங்கும் பிரிக்கப்பட்ட குழந்தை செயல்முறைகளை நீங்கள் உருவாக்கலாம்:

const { spawn } = require('child_process');
const fs = require('fs');

// Create a detached process
const child = spawn('node', ['long_running_script.js'], {
  detached: true,
  stdio: ['ignore',
    fs.openSync('output.log', 'w'),
    fs.openSync('error.log', 'w')
  ]
});

// Unref the child to allow the parent to exit independently
child.unref();

console.log(`Started detached process with PID: ${child.pid}`);
console.log('Parent will exit while child continues running.');

// The parent can now exit, and the child will continue running

நடைமுறை எடுத்துக்காட்டுகள்

ஒரு எளிய பணி வரிசையை உருவாக்குதல்

// In tasks.js (parent)
const { fork } = require('child_process');
const numCPUs = require('os').cpus().length;

class TaskQueue {
  constructor() {
    this.tasks = [];
    this.workers = [];
    this.maxWorkers = numCPUs;
  }

  addTask(task) {
    this.tasks.push(task);
    this.runNext();
  }

  runNext() {
    // If we have tasks and available workers
    if (this.tasks.length > 0 && this.workers.length < this.maxWorkers) {
      const task = this.tasks.shift();
      const worker = fork('worker.js');

      console.log(`Starting worker for task ${task.id}`);
      this.workers.push(worker);

      worker.send(task);

      worker.on('message', (result) => {
        console.log(`Task ${task.id} completed with result:`, result);

        // Remove this worker from our workers list
        this.workers = this.workers.filter(w => w !== worker);

        // Run the next task if we have one
        this.runNext();
      });

      worker.on('error', (err) => {
        console.error(`Worker for task ${task.id} had an error:`, err);
        this.workers = this.workers.filter(w => w !== worker);
        this.runNext();
      });

      worker.on('exit', (code) => {
        if (code !== 0) {
          console.error(`Worker for task ${task.id} exited with code ${code}`);
        }
      });
    }
  }

// Usage
const queue = new TaskQueue();

// Add some tasks
for (let i = 1; i <= 10; i++) {
  queue.addTask({
    id: i,
    type: 'calculation',
    data: Array.from({ length: 1000000 }, () => Math.random())
  });
}
// In worker.js
process.on('message', (task) => {
  console.log(`Worker ${process.pid} received task ${task.id}`);

  // Simulate CPU-intensive work
  let result;

  if (task.type === 'calculation') {
    // For example, find sum and average
    const sum = task.data.reduce((acc, val) => acc + val, 0);
    const avg = sum / task.data.length;

    result = { sum, avg };
  }

  // Send result back to parent
  process.send({ taskId: task.id, result });

  // Exit this worker
  process.exit(0);
});

வெளிப்புற பயன்பாடுகளை இயக்குதல்

const { spawn } = require('child_process');
const path = require('path');
const fs = require('fs');

// Function to convert a video using ffmpeg
function convertVideo(inputFile, outputFile, options = {}) {
  return new Promise((resolve, reject) => {
    // Make sure input file exists
    if (!fs.existsSync(inputFile)) {
      return reject(new Error(`Input file ${inputFile} does not exist`));
    }

    // Prepare ffmpeg arguments
    const args = ['-i', inputFile];

    if (options.scale) {
      args.push('-vf', `scale=${options.scale}`);
    }

    if (options.format) {
      args.push('-f', options.format);
    }

    args.push(outputFile);

    // Spawn ffmpeg process
    const ffmpeg = spawn('ffmpeg', args);

    // Collect output for logging
    let stdoutData = '';
    let stderrData = '';

    ffmpeg.stdout.on('data', (data) => {
      stdoutData += data;
    });

    ffmpeg.stderr.on('data', (data) => {
      stderrData += data;
    });

    // Handle process completion
    ffmpeg.on('close', (code) => {
      if (code === 0) {
        resolve({
          inputFile,
          outputFile,
          stdout: stdoutData,
          stderr: stderrData
      });
      } else {
        reject(new Error(`ffmpeg exited with code ${code}\n${stderrData}`));
      }
    });

    // Handle process errors
    ffmpeg.on('error', reject);
   });
}

// Example usage (commented out)
/*
convertVideo('input.mp4', 'output.webm', {
  scale: '640:480',
  format: 'webm'
})
  .then(result => {
    console.log('Video conversion successful!');
    console.log(`Output file: ${result.outputFile}`)
;   })
  .catch(error => {
    console.error('Video conversion failed:', error.message);
  });
*/

சிறந்த நடைமுறைகள்

உள்ளீட்டு சுத்திகரிப்பு: கட்டளை ஊசி தாக்குதல்களைத் தடுக்க எப்போதும் பயனர் உள்ளீடுகளை சுத்திகரிக்கவும், குறிப்பாக exec() உடன்
வள மேலாண்மை: குழந்தை செயல்முறைகளால் பயன்படுத்தப்படும் வளங்களை (நினைவகம், கோப்பு விவரிப்பான்கள்) கண்காணித்து கையாளவும்
பிழை கையாளுதல்: குழந்தை செயல்முறைகளுக்கு எப்போதும் சரியான பிழை கையாளுதல் இருக்க வேண்டும்
சரியான முறையைத் தேர்ந்தெடுக்கவும்:
  • வரையறுக்கப்பட்ட வெளியீட்டுடன் கூடிய எளிய கட்டளைகளுக்கு exec() ஐப் பயன்படுத்தவும்
  • நீண்ட-இயங்கும் செயல்முறைகள் அல்லது பெரிய வெளியீடுகளுக்கு spawn() ஐப் பயன்படுத்தவும்
  • CPU-தீவிர Node.js செயல்பாடுகளுக்கு fork() ஐப் பயன்படுத்தவும்
சுத்தம்: குழந்தை செயல்முறைகள் இனி தேவையில்லாதபோது அவற்றை சரியாகக் கொல்லவும்
ஒரே நேரத்தில் இயங்கும் எண்ணிக்கையைக் கட்டுப்படுத்தவும்: கணினி சுமையைத் தவிர்க்க ஒரே நேரத்தில் இயங்கும் குழந்தை செயல்முறைகளின் எண்ணிக்கையைக் கட்டுப்படுத்தவும்

⚠️ எச்சரிக்கை:

பல குழந்தை செயல்முறைகளை இயக்குவது விரைவாக கணினி வளங்களை தீர்த்துவிடும். எப்போதும் விகித வரம்பு மற்றும் ஒரே நேரத்தில் இயங்கும் கட்டுப்பாட்டை செயல்படுத்தவும்.

பாதுகாப்பு பரிசீலனைகள்

கட்டளை ஊசி: exec() அல்லது spawn() க்கு சுத்திகரிக்கப்படாத பயனர் உள்ளீட்டை நேரடியாக ஒருபோதும் அனுப்ப வேண்டாம்
சூழல் மாறிகள்: குழந்தை செயல்முறைகளுக்கு சூழல் மாறிகளை அனுப்புவதில் கவனமாக இருங்கள்
கோப்பு அணுகல்: குழந்தை செயல்முறைகளுக்கு இருக்கக்கூடிய அனுமதிகளைப் புரிந்து கொள்ளுங்கள்
வள வரம்புகள்: குழந்தை செயல்முறைகளுக்கான நேரக்கெடு மற்றும் நினைவக வரம்புகளை செயல்படுத்துவதைக் கவனியுங்கள்

பயிற்சி

சரியான தொகுதி பெயரை தேர்வு செய்யவும்.

The ______ module provides the ability to spawn child processes in Node.js.

cluster
✗ தவறு! "cluster" தொகுதி கிளஸ்டரிங் மூலம் பயன்பாட்டு செயல்திறனை மேம்படுத்த உதவுகிறது, ஆனால் குழந்தை செயல்முறைகளைத் தோற்றுவிக்காது
worker_threads
✗ தவறு! "worker_threads" தொகுதி worker threads ஐ உருவாக்குகிறது, குழந்தை செயல்முறைகளை அல்ல
child_process
✓ சரி! "child_process" தொகுதி Node.js இல் குழந்தை செயல்முறைகளைத் தோற்றுவிக்கும் திறனை வழங்குகிறது
process
✗ தவறு! "process" தொகுதி தற்போதைய செயல்முறை பற்றிய தகவல்களை வழங்குகிறது, ஆனால் குழந்தை செயல்முறைகளைத் தோற்றுவிக்காது